package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.InitReplySmsDTO;
import com.xbongbong.paas.pojo.dto.SmsCronTabAsyncDTO;
import com.xbongbong.paas.pojo.dto.SmsCronTabDTO;
import com.xbongbong.paas.service.SmsReplyService;
import com.xbongbong.paas.service.SmsSendService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.sms.pojo.dto.SmsPullReplyDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsPushBalanceDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsUpdateStatusDTO;
import com.xbongbong.pro.sms.pojo.vo.SmsPullReplyVO;
import com.xbongbong.pro.sms.pojo.vo.SmsRabbitMqVO;
import com.xbongbong.pro.sms.pojo.vo.SmsUpdateStatusVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.model.CompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author chy
 * @ProjectName xbb-web-script
 * @Description: 短信相关数据接口
 * @date 2019/10/24 15:34
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/sms")
public class SmsScriptController {

    private static final Logger LOG = LoggerFactory.getLogger(SmsScriptController.class);

    @Lazy
    @Resource
    private SmsSendService smsSendService;
    @Resource
    private SmsReplyService smsReplyService;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private CompanyModel companyModel;

    /**
     * 空间畅想短信定时发送任务脚本
     * @param smsCronTabDTO
     * @param br
     * @return
     * 创建时间 2019/10/19 4:47 AM
     * 修改时间 2019/10/19 4:47 AM
     * @author youli.chen
     * @since v1.0
     * @version v1.0
     */
    @RequestMapping(value = "/smsCronTab", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String smsCronTab(@Valid SmsCronTabDTO smsCronTabDTO, BindingResult br) {
        XbbResponse<SmsRabbitMqVO> response;
        try {
            response = updateSmsStatus(smsCronTabDTO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 通过crontab定时任务每十分钟不停的拉取并更新短信状态
     *
     * @param updateStatusDTO 入参
     * @param br
     * @return
     * @author youli.chen
     * @addTime: 2019-10-21 13:42
     * @modified by:
     * @updateTime: 2019-10-21 13:42
     * @version
     * @since
     */
    @RequestMapping(value = "/cronTabUpdateStatus", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cronTabUpdateStatus(@Valid SmsUpdateStatusDTO updateStatusDTO, BindingResult br) {
        XbbResponse<SmsUpdateStatusVO> response;
        try {
            SmsUpdateStatusVO updateStatusVO = smsSendService.cronTabUpdateStatus(updateStatusDTO);
            response = new XbbResponse<>(updateStatusVO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }


    /**
     * 线程
     * @param smsCronTabDTO
     * @return
     * @throws XbbException
     */
    public XbbResponse<SmsRabbitMqVO> updateSmsStatus(SmsCronTabDTO smsCronTabDTO) throws XbbException {
        SmsRabbitMqVO smsRabbitMqVO = new SmsRabbitMqVO();
        // 校验定时任务
        String key = smsCronTabDTO.getKey();
        if (!Objects.equals(key, BasicConstant.TASK_SECRET_KEY)) {
            LOG.error("短信定时发送任务脚本校验 密码错误，停止定时任务！");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100066);
        }

        String corpid = smsCronTabDTO.getCorpid();
        // 有指定公司
        if (StringUtil.isNotEmpty(corpid)) {
            SmsCronTabAsyncDTO smsCronTabAsyncDTO = new SmsCronTabAsyncDTO();
            smsCronTabAsyncDTO.setCorpid(corpid);
            smsSendService.updateSmsStatusAsync(smsCronTabAsyncDTO);
        } else {
            // 全公司执行
            SmsCronTabAsyncDTO smsCronTabAsyncDTO = new SmsCronTabAsyncDTO();
            smsSendService.updateSmsStatusAsync(smsCronTabAsyncDTO);
        }
        return new XbbResponse<>(smsRabbitMqVO);
    }

    /**
     * 通过crontab定时任务不停的拉取回复短信
     *
     * @param smsPullReplyDTO 入参
     * @param br
     * @return
     * @author youli.chen
     * @addTime: 2019-11-21 13:42
     * @modified by:
     * @updateTime: 2019-10-21 13:42
     * @version
     * @since
     */
    @RequestMapping(value = "/cronTabPullSmsReply", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cronTabPullSmsReply(@Valid SmsPullReplyDTO smsPullReplyDTO, BindingResult br) {
        XbbResponse<SmsPullReplyVO> response;
        try {
            SmsPullReplyVO smsPullReplyVO = smsReplyService.cronTabPullSmsReply(smsPullReplyDTO);
            response = new XbbResponse<>(smsPullReplyVO);
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 通过crontab定时任务检查短信额度发送预警短信
     *
     * @param smsPullReplyDTO 入参
     * @param br
     * @return
     * @author youli.chen
     * @addTime: 2019-11-21 13:42
     * @modified by:
     * @updateTime: 2019-10-21 13:42
     * @version
     * @since
     */
    @RequestMapping(value = "/cronTabGetSmsBalance", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cronTabGetSmsBalance(@Valid SmsPushBalanceDTO smsPushBalanceDTO, BindingResult br) {
        XbbResponse<SmsPullReplyVO> response;
        try {
            smsSendService.getBalance();
            response = new XbbResponse<>();
        } catch (XbbException e) {
            response = new XbbResponse<>(e);
        }
        return JSON.toJSONString(response);
    }

    /**
     * 初始化公司收件箱菜单脚本
     * @param initReplySmsDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/initReplySms", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initReplySms(@RequestBody @Valid InitReplySmsDTO initReplySmsDTO, BindingResult br) throws Exception {
        // 校验code
        if (!proBaseConfig.getXbbCode().equals(initReplySmsDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }

        String userId = initReplySmsDTO.getUserId();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("status", 1);
        int total = companyModel.getEntitysCount(param);
        int pageSize = 1000;

        for(int i = 0; i < total; i += pageSize) {
            param.clear();
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("status", 1);
            param.put("start", i);
            param.put("pageNum", pageSize);
            param.put("columns", "corpid");
            List<CompanyEntity> companyEntityList = companyModel.findEntitys(param);
            if (Objects.isNull(companyEntityList) || companyEntityList.isEmpty()) {
                continue;
            }

            List<String> corpids = new ArrayList<>(pageSize);
            companyEntityList.forEach(item -> {
                corpids.add(item.getCorpid());
            });

            Map<String,Object> appParam = new HashMap<>();
            appParam.put("del", DelEnum.NORMAL.getDel());
            appParam.put("corpidIn", corpids);
            appParam.put("alias", XbbRefTypeEnum.GROUP_MESSAGE.getAlias());
            List<PaasAppEntity> entitys = paasAppModel.findEntitys(appParam);
            if (Objects.isNull(entitys) || entitys.isEmpty()) {
                continue;
            }
            Integer saasMark = SaasMarkEnum.SAAS.getCode();
            List<PaasMenuEntity> menuAddList = new ArrayList<>();
            Long now = DateTimeUtil.getInt();

            List<Long> appIds = new ArrayList<>(entitys.size());
            entitys.forEach(item -> appIds.add(item.getId()));
            Map<String, Object> menuParam = new HashMap<>();
            menuParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            menuParam.put("appIdList", appIds);
            menuParam.put("parentId", 0);
            menuParam.put("columns", "app_id");
            List<PaasMenuEntity> menuEntities = paasMenuModel.findEntitys(menuParam);
            Map<Long, Integer> appIdAndCount = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasMenuEntity menuEntity : menuEntities) {
                Long appId = menuEntity.getAppId();
                Integer count = appIdAndCount.get(appId);
                if (count == null) {
                    appIdAndCount.put(appId, 0);
                } else {
                    count += 1;
                    appIdAndCount.put(appId, count);
                }
            }
            for (PaasAppEntity item : entitys) {
                PaasMenuEntity paasMenuEntity = new PaasMenuEntity();
                paasMenuEntity.setCorpid(item.getCorpid());
                paasMenuEntity.setAppId(item.getId());
                paasMenuEntity.setCreatorId(userId);
                paasMenuEntity.setAlias(XbbRefTypeEnum.REPLY_VIEW.getAlias());
                paasMenuEntity.setColor(AccessLinkEnum.REPLY_VIEW.getColor());
                paasMenuEntity.setIcon(AccessLinkEnum.REPLY_VIEW.getIcon());
                paasMenuEntity.setParentId(0L);
                paasMenuEntity.setSaasMark(saasMark);
                paasMenuEntity.setUrl(AccessLinkEnum.REPLY_VIEW.getUrl());
                paasMenuEntity.setType(MenuTypeEnum.MENU.getType());
                paasMenuEntity.setEnable(BasicConstant.ONE);
                paasMenuEntity.setName(XbbRefTypeEnum.REPLY_VIEW.getName());
                paasMenuEntity.setAddTime(now);
                paasMenuEntity.setUpdateTime(now);

                Integer count = appIdAndCount.get(item.getId());
                if (count != null) {
                    count += 1;
                    paasMenuEntity.setSort(count);
                } else {
                    paasMenuEntity.setSort(100);
                }

                menuAddList.add(paasMenuEntity);
            }
            try {
                paasMenuModel.insertBatch(menuAddList);
            } catch (Exception e) {
                LOG.error("收件箱menu数据库批量插入菜单出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        return "success";
    }
}
